package com.css.zfzx.fxpg.common.utils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;

/**
 * @author leon
 * @date 2020/12/8 18:21
 */
public class MathUtil {

    /**
     * 一元线性拟合 y = a + b*x
     * <p>
     * reuslt[0] = a result[1] = b result[2] 相关系数 result[3] 决定系数
     * result[4] 点数量(长度) result[5] 自由度
     *
     * @param x
     * @param y
     */
    public static double[] lineFitting(Double x[], Double y[]) {
        int size = x.length;
        double xmean = 0.0;
        double ymean = 0.0;
        double xNum = 0.0;
        double yNum = 0.0;
        double xyNum = 0;
        double xNum2 = 0;
        double yNum2 = 0;
        double rss = 0;
        double tss = 0;
        double result[] = new double[6];

        for (int i = 0; i < size; i++) {
            xmean += x[i];
            ymean += y[i];
            xNum2 += x[i] * x[i];
            yNum2 += y[i] * y[i];
            xyNum += x[i] * y[i];
        }
        xNum = xmean;
        yNum = ymean;
        xmean /= size;
        ymean /= size;

        double sumx2 = 0.0f;
        double sumxy = 0.0f;
        for (int i = 0; i < size; i++) {
            sumx2 += (x[i] - xmean) * (x[i] - xmean);
            sumxy += (y[i] - ymean) * (x[i] - xmean);
        }

        double b = sumxy / sumx2;
        double a = ymean - b * xmean;

        result[0] = a;
        result[1] = b;
        System.out.println("a = " + a + ", b=" + b);

        double correlation = (xyNum - xNum * yNum / size)
                / Math.sqrt((xNum2 - xNum * xNum / size) * (yNum2 - yNum * yNum / size));

        System.out.println("相关系数：" + correlation);
        result[2] = correlation;

        for (int i = 0; i < size; i++) {
            rss += (y[i] - (a + b * x[i])) * (y[i] - (a + b * x[i]));
            tss += (y[i] - ymean) * (y[i] - ymean);
        }

        double r2 = 1 - (rss / (size - 1 - 1)) / (tss / (size - 1));

        result[3] = r2;
        System.out.println("决定系数" + r2);

        result[4] = x.length;
        result[5] = x.length - 1 - 1;

        return result;
    }


    public static void main(String[] args) {
        double x1 = 2;
        double y1 = 6;

        double x2 = 5;
        double y2 = 9;

        double k1 = Math.log(y2 / y1) / Math.log(x1 / x2);
        k1 = getPrecision(k1, 2);
        double k0 = Math.pow(x1, k1) * y1;
        k0 = getPrecision(k0, 2);

        System.out.println("k1=" + k1 + ", k0=" + k0);
        double x = 10;
        double y = k0 * Math.pow(x, -k1);
        y = getPrecision(y, 2);
        System.out.println(y);

        double n = 1.0 / 3;
        System.out.println(Math.pow(7, 1d / 3));
    }

    /**
     * double类型保留小数
     *
     * @param f
     * @param newScale 保留几位小数
     * @return
     */
    public static double getPrecision(double f, int newScale) {
        BigDecimal bg = new BigDecimal(f);
        /**
         * 参数：
         newScale - 要返回的 BigDecimal 值的标度。
         roundingMode - 要应用的舍入模式。
         返回：
         一个 BigDecimal，其标度为指定值，其非标度值可以通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定。
         */
        double f1 = bg.setScale(newScale, BigDecimal.ROUND_HALF_UP).doubleValue();
        return f1;
    }
}
